package com.iot.service.mqtt.codec.decoder;

import com.iot.service.mqtt.model.fix.TlMqttFixedHead;
import com.iot.service.mqtt.model.payload.TlMqttPublishPayload;
import com.iot.service.mqtt.model.request.TlMqttPublishReq;
import com.iot.service.mqtt.model.variable.TlMqttPublishVariableHead;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.mqtt.MqttMessageType;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @Author: hszhou
 * @Date: 2024/11/30 15:12
 * @Description: 收到发送者的消息解码器
 */
@Component
public class TlMqttPublishDecoder {

    private static final Logger logger = LoggerFactory.getLogger(TlMqttPublishDecoder.class);

    public TlMqttPublishReq build(ByteBuf buf, int type, int remainingLength) {
        TlMqttFixedHead fixedHead = decodeFixedHeader(type, remainingLength);
        MqttQoS qos = fixedHead.getQos();
        TlMqttPublishVariableHead variableHead = decodeVariableHeader(buf, qos);
        TlMqttPublishPayload payload = decodePayLoad(buf);
        return new TlMqttPublishReq(fixedHead, variableHead, payload);
    }

    TlMqttFixedHead decodeFixedHeader(int type, int remainingLength) {
        TlMqttFixedHead fixedHead = new TlMqttFixedHead();
        int messageType = type >> 4;
        int retain = (type) & 1;
        int qos = (type >> 1) & 3;
        int dup = (type >> 3) & 1;
        fixedHead.setMessageType(MqttMessageType.valueOf(messageType));
        fixedHead.setDup(dup != 0);
        fixedHead.setQos(MqttQoS.valueOf(qos));
        fixedHead.setRetain(retain != 0);
        fixedHead.setLength(remainingLength);
        logger.debug("parse 【PUBLISH】fixedHead:type=【{}】,message=【{}】,dup=【{}】,qos=【{}】,retain=【{}】，length=【{}】", type, messageType, dup, qos, retain, remainingLength);
        return fixedHead;
    }


    TlMqttPublishVariableHead decodeVariableHeader(ByteBuf buf, MqttQoS qos) {
        int topicLength = buf.readUnsignedShort();
        byte[] topic = new byte[topicLength];
        buf.readBytes(topic);
        String topicName = new String(topic);
        if (qos != MqttQoS.AT_MOST_ONCE) {
            int messageId = buf.readUnsignedShort();
            return TlMqttPublishVariableHead.build(topicName, (long) messageId);
        }
        return TlMqttPublishVariableHead.build(topicName);
    }


    TlMqttPublishPayload decodePayLoad(ByteBuf buf) {
        int contentLength = buf.readableBytes();
        byte[] contentByte = new byte[contentLength];
        buf.readBytes(contentByte);
        String content = new String(contentByte);
        logger.debug("parse 【PUBLISH】 payload【{}】", content);
        return TlMqttPublishPayload.build(content);
    }
}
